package com.huateng.springcloud.lock;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


/**
 * @author Evan
 * @create 2021/7/28 14:28
 */
public class ReentrantLockTest {

    public static final Logger LOGGER = LoggerFactory.getLogger(ReentrantLockTest.class);

    private ReentrantLock lock = new ReentrantLock();

    public Condition condition1 = lock.newCondition();
    public Condition condition2 = lock.newCondition();

    public static void main(String[] args) throws Exception {
        ReentrantLockTest test = new ReentrantLockTest();
        new Thread(test::awaitCondition1).start();
        new Thread(test::awaitCondition2).start();

        Thread.sleep(1000L);
        test.signalConditon1();

        Thread.sleep(1000L);
        test.signalConditon2();

    }

    public void awaitCondition1(){
        String threadName = Thread.currentThread().getName();
        try {
            lock.lock();
            LOGGER.info("{} {} await Condition1", new Date(), threadName);
            long timeBefore = System.currentTimeMillis();
            condition1.await();
            long timeAfter = System.currentTimeMillis();
            LOGGER.info("{} {} notify Condition1", new Date(), threadName);
            LOGGER.info("{} {} wait {}ms", new Date(), threadName, timeAfter - timeBefore);

        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void awaitCondition2(){
        String threadName = Thread.currentThread().getName();
        try {
            lock.lock();
            LOGGER.info("{} {} await Condition2", new Date(), threadName);
            long timeBefore = System.currentTimeMillis();
            condition1.await();
            long timeAfter = System.currentTimeMillis();
            LOGGER.info("{} {} notify Condition2", new Date(), threadName);
            LOGGER.info("{} {} wait {}ms", new Date(), threadName, timeAfter - timeBefore);

        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void signalConditon1(){
        try {
            lock.lock();
            LOGGER.info("{} {} Conditon1 signal all", new Date(), Thread.currentThread().getName());
            condition1.signalAll();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void signalConditon2(){
        try {
            lock.lock();
            LOGGER.info("{} {} Conditon2 signal all", new Date(), Thread.currentThread().getName());
            condition2.signalAll();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
